package source.model;

import source.model.type.GameObjectType;
import source.model.type.AreaEffectType;

public abstract class AreaEffect implements GameObject{

	private final GameObjectType gameObjectType = GameObjectType.AREAEFFECT;
	private static int nextId = 0;
	private final ObjectID oid;
	private boolean valid = true;
	private int x = -1;
	private int y = -1;
	private AreaEffectType aet;
	
	public AreaEffect()
	{
		oid = new ObjectID( gameObjectType.getId() + "." + nextId++ );
	}

	public AreaEffect(AreaEffectType aet){
		this.aet = aet;
		oid = new ObjectID( gameObjectType.getId() + "." + nextId++ );
	}
	
	public boolean isValid()
	{
		return valid;
	}
	
	/**
	 * @return oid: ObjectID, the object ID for the AreaEffect
	 */
	
	public ObjectID objectID()
	{
		return oid;
	}
	
	/**
	 * @return gameObjectType: GameObjectType, the type of game object AreaEffect is
	 */
	
	public GameObjectType objectType()
	{
		return gameObjectType;
	}
	
	/**
	 * @return false, since this GameObject is not owned by the player
	 */
	
	public boolean isPlayerOwned()
	{
		return false;
	}

	public void setType(AreaEffectType aet){
		this.aet = aet;
	}

	public AreaEffectType getType(){
		return aet;
	}	
	
	/**
	 * We need to decide here how to have the area effect interact with the unit that
	 * has come into contact with it. I recommend using the TerrainUtility class so
	 * that we can close this class from having to be modified.
	 * The boolean returned needs to mark whether the Unit effect would caused a
	 * change to the unit state (i.e., not valid, position changed)
	 * @param u
	 */
	public abstract boolean doEffect( Unit u );

	public abstract boolean doEffect(DataHandler dh, Unit u);
	
	/**
	 * This method is used to mark the object as having been forcibly moved (i.e.,
	 * Unit teleported using Area Effect) and that it's possition needs to be changed.
	 * @param x new x-coordinate
	 * @param y new y-coordinate
	 * @return true if object allowed the forced change, false otherwise
	 */
	public boolean changePosition( int x, int y ){
		this.x = x;
		this.y = y;
		return true;
	}
	
	/**
	 * Queries the object to find out if the changePositionFlag is set, meaning
	 * the object's position in pMap must be updated
	 * @return true if flag set; false otherwise
	 */
	public boolean changePositionFlag(){
		if ((x == -1) && (y == -1)) return false;
		return true;
	}
	
	public Position newPosition(){
		return new Position(x,y);
	}
	
	/**
	 * Once the DataHandler resets the position of the object, it calls this method to
	 * let the object know that it is now no longer in a "Forced Position Change" 
	 * state
	 * @return true if the object reset it's flag, false otherwise
	 */
	public boolean resetPositionChangedFlag(){
		x = -1;
		y = -1;
		return true;
	}
	
	public void invalidate(){
		valid = false;
	}
	
	public java.util.Hashtable<String, String> getViewData()
	{
		java.util.Hashtable<String, String> viewData = new java.util.Hashtable<String, String>();
		
		viewData.put("Object ID", oid.getID());
		viewData.put("Game Object Type", gameObjectType.name());
		
		return viewData;
	}
}
